package com.egrand.sweetapi.plugin.db.service.impl;

import cn.hutool.core.util.StrUtil;
import cn.hutool.cron.CronUtil;
import cn.hutool.cron.task.Task;
import com.egrand.sweetapi.plugin.db.configure.EgdTenantDataSourceProperties;
import com.egrand.sweetapi.plugin.db.provider.EgdTenantDataSourceProvider;
import com.egrand.sweetapi.plugin.db.service.EgdTenantDataSourceService;
import com.egrand.sweetapi.starter.db.DynamicRoutingDataSource;
import com.egrand.sweetapi.starter.db.creator.DataSourceCreator;
import com.egrand.sweetapi.starter.db.spring.boot.autoconfigure.DataSourceProperty;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import javax.sql.DataSource;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

@Component
@Slf4j
public class EgdTenantDataSourceServiceImpl implements EgdTenantDataSourceService {

    @Autowired
    private DataSource dataSource;

    @Autowired
    private EgdTenantDataSourceProvider egdTenantDataSourceProvider;

    @Autowired
    private DataSourceCreator dataSourceCreator;

    @Autowired
    private EgdTenantDataSourceProperties egdTenantDataSourceProperties;

    private static String dbCronJobId = "";

    /**
     * 是否启动过定时任务
     */
    private static boolean isStarted = false;

    @Override
    public Boolean pullDataSource() {
        DynamicRoutingDataSource ds = (DynamicRoutingDataSource) dataSource;
        Map<String, DataSourceProperty> dataSourcePropertyMap = this.egdTenantDataSourceProvider.loadDataSourceProperty();
        if (null == dataSourcePropertyMap || dataSourcePropertyMap.size() == 0){
            return true;
        }
        Map<String, DataSource> dataSourceMap = ds.getCurrentDataSources();
        // 判断需要添加的数据源连接是否存在，存在则不初始化连接
        dataSourcePropertyMap.keySet().forEach(key -> {
            if (!dataSourceMap.containsKey(key)){
                DataSource dataSource = dataSourceCreator.createDataSource(dataSourcePropertyMap.get(key));
                ds.addDataSource(key, dataSource);
            } else {
                log.info("DataSources " + key + " is exist!");
            }
        });
        return true;
    }

    @Override
    public Boolean removeDataSource() {
        DynamicRoutingDataSource ds = (DynamicRoutingDataSource) dataSource;
        Map<String, DataSourceProperty> dataSourcePropertyMap = this.egdTenantDataSourceProvider.loadDataSourceProperty();
        if (null == dataSourcePropertyMap || dataSourcePropertyMap.size() == 0){
            return true;
        }
        Map<String, DataSource> dataSourceMap = ds.getCurrentDataSources();
        // 判断当前数据源连接池中是否存在多余的连接，存在则删除
        if (null != dataSourceMap) {
            List<String> keys = new ArrayList<String>();
            dataSourceMap.keySet().forEach(key -> {
                if (!dataSourcePropertyMap.containsKey(key) && !"master".equalsIgnoreCase(key)){
                    log.info(key + " is not exist will be delete");
                    keys.add(key);
                }
            });
            if (keys.size() != 0) {
                keys.forEach(key -> ds.removeDataSource(key));
            }
        }
        return true;
    }

    @Override
    public void schedule() {
        if (StrUtil.isNotEmpty(this.dbCronJobId))
            return;
        if (!CronUtil.getScheduler().isStarted()) {
            CronUtil.setMatchSecond(true);
            CronUtil.start();
            isStarted = true;
        }
        this.dbCronJobId = CronUtil.schedule(egdTenantDataSourceProperties.getCron(), (Task) () -> this.pullDataSource());
        this.pullDataSource();
    }

    @Override
    public void deschedule() {
        if (StrUtil.isNotEmpty(this.dbCronJobId)) {
            CronUtil.remove(this.dbCronJobId);
            if (isStarted) {
                isStarted = false;
                CronUtil.stop();
            }
            this.dbCronJobId = "";
        }
    }
}
